﻿using System;
using System.Collections.Generic;
using System.Text;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Criterion;
using Iesi.Collections.Generic;
using System.Reflection;
using System.Configuration;
using System.Collections;
using System.Data;
using System.Security.Cryptography;
using System.Globalization;

namespace DBA.Data.Hibernate
{
    /// <summary>
    /// NHibernate查询
    /// </summary>
    public class NHibernateQuery
    {
        private ISession _session;

        public ISession CurrentSession
        {
            get { return _session; }
            set { _session = value; }
        }
        //private static string connString = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();

        /// <summary>
        /// 
        /// </summary>
        public NHibernateQuery()
        {
            try
            {
                _session = SessionManager.GetSession();
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }

        #region 查询参数设置 GetICriteria
        /// <summary>
        /// 查询参数设置
        /// </summary>
        /// <param name="icr">ICriteria接口</param>
        /// <param name="cons">查询条件数组</param>
        /// <returns>已设置的ICriteria接口</returns>
        private ICriteria GetICriteria(ICriteria icr, Condition[] cons)
        {
            if (cons != null)
            {
                foreach (Condition item in cons)
                {
                    switch (item.OpType)
                    {
                        case Op.Ge:
                            icr.Add(Expression.Ge(item.Name, item.Value1));
                            break;
                        case Op.Gt:
                            icr.Add(Expression.Gt(item.Name, item.Value1));
                            break;
                        case Op.Le:
                            icr.Add(Expression.Le(item.Name, item.Value1));
                            break;
                        case Op.Lt:
                            icr.Add(Expression.Lt(item.Name, item.Value1));
                            break;
                        case Op.Between:
                            icr.Add(Expression.Between(item.Name, item.Value1, item.Value2));
                            break;
                        case Op.Eq:
                            icr.Add(Expression.Eq(item.Name, item.Value1));
                            break;
                        case Op.Like:
                            icr.Add(Expression.Like(item.Name, item.Value1.ToString()));
                            break;
                        case Op.NotEq:
                            icr.Add(Restrictions.Not(Expression.Eq(item.Name, item.Value1)));
                            break;
                        case Op.In:
                            icr.Add(Expression.In(item.Name, item.Values));
                            break;
                        case Op.NotIn:
                            icr.Add(Restrictions.Not(Expression.In(item.Name, item.Values)));
                            break;
                        case Op.NotBetween:
                            icr.Add(Restrictions.Not(Expression.Between(item.Name, item.Value1, item.Value2)));
                            break;
                        case Op.TableLink:
                            icr.CreateCriteria(item.Value1.ToString());
                            break;
                        case Op.Or:
                            if (item.OrType == OrQuery.EqAndEq)
                                icr.Add(Restrictions.Or(Expression.Eq(item.Name, item.Value1), Expression.Eq(item.Name, item.Value2)));
                            break;
                        case Op.OrderBy:
                            icr.AddOrder(new Order(item.Name, (bool)item.Value1));
                            break;
                    }
                }
            }
            icr.SetResultTransformer(NHibernate.CriteriaUtil.DistinctRootEntity);
            return icr;
        }

        /// <summary>
        /// 聚合查询参数设置
        /// </summary>
        /// <param name="icr">ICriteria接口</param>
        /// <param name="cons">查询条件数组</param>
        /// <returns>已设置的ICriteria接口</returns>
        private ICriteria GetCountICriteria(ICriteria icr, Condition[] cons)
        {
            if (cons != null)
            {
                foreach (Condition item in cons)
                {
                    switch (item.OpType)
                    {
                        case Op.Ge:
                            icr.Add(Expression.Ge(item.Name, item.Value1));
                            break;
                        case Op.Gt:
                            icr.Add(Expression.Gt(item.Name, item.Value1));
                            break;
                        case Op.Le:
                            icr.Add(Expression.Le(item.Name, item.Value1));
                            break;
                        case Op.Lt:
                            icr.Add(Expression.Lt(item.Name, item.Value1));
                            break;
                        case Op.Between:
                            icr.Add(Expression.Between(item.Name, item.Value1, item.Value2));
                            break;
                        case Op.Eq:
                            icr.Add(Expression.Eq(item.Name, item.Value1));
                            break;
                        case Op.Like:
                            icr.Add(Expression.Like(item.Name, item.Value1.ToString()));
                            break;
                        case Op.NotEq:
                            icr.Add(Restrictions.Not(Expression.Eq(item.Name, item.Value1)));
                            break;
                        case Op.In:
                            icr.Add(Expression.In(item.Name, item.Values));
                            break;
                        case Op.NotIn:
                            icr.Add(Restrictions.Not(Expression.In(item.Name, item.Values)));
                            break;
                        case Op.NotBetween:
                            icr.Add(Restrictions.Not(Expression.Between(item.Name, item.Value1, item.Value2)));
                            break;
                        case Op.TableLink:
                            icr.CreateCriteria(item.Value1.ToString());
                            break;
                        case Op.Or:
                            if (item.OrType == OrQuery.EqAndEq)
                                icr.Add(Restrictions.Or(Expression.Eq(item.Name, item.Value1), Expression.Eq(item.Name, item.Value2)));
                            break;
                    }
                }
            }
            return icr;
        }
        #endregion


       

        /// <summary>
        /// 根据指定的条件返回对象集合
        /// </summary>
        /// <typeparam name="T">要查询的对象</typeparam>
        /// <param name="cons">查询条件集合</param>
        /// <returns></returns>
        public IList<T> SelectObjects<T>(Condition[] cons) where T : new()
        {
            try
            {
                ICriteria criteria = _session.CreateCriteria(typeof(T));

                criteria = this.GetICriteria(criteria, cons);

                return criteria.List<T>();
            }
            catch (HibernateException ex)
            {

                throw new Exception(ex.Message);
            }
          
        }

       

        /// <summary>
        /// 分页返回对象集合
        /// </summary>
        /// <typeparam name="T">要查询的对象</typeparam>
        /// <param name="cons">查询条件集合</param>
        /// <param name="currentPageIndex">当前页数</param>
        /// <param name="pageSize">每页条数</param>
        /// <param name="recordCount">记录总数</param>
        /// <returns></returns>
        public IList<T> SelectObjects<T>(Condition[] cons, int currentPageIndex, int pageSize) where T : new()
        {
            try
            {
                ICriteria criteria = _session.CreateCriteria(typeof(T));

                criteria = this.GetICriteria(criteria, cons);
                //设置分页  
                criteria.SetFirstResult((currentPageIndex - 1) * pageSize).SetMaxResults(pageSize);
                return criteria.List<T>();
            }
            catch (HibernateException ex)
            {

                throw new Exception(ex.Message);
            }
        }


        /// <summary>
        /// 获取满足条件的记录数
        /// </summary>
        /// <typeparam name="T">要查询的对象</typeparam>
        /// <param name="cons">查询条件集合</param>
        /// <returns></returns>
        public int GetMaxCount<T>(Condition[] cons) where T : new()
        {
            try
            {
                ICriteria criteria = _session.CreateCriteria(typeof(T));
                criteria = this.GetCountICriteria(criteria, cons);
                return criteria.SetProjection(Projections.Count(this.FindProName<T>())).UniqueResult<Int32>();
            }
            catch (HibernateException ex)
            {

                throw new Exception(ex.Message);
            }
        }

        #region 返回这个实体类中一个属性的反射信息
        /// <summary>
        /// 返回这个实体类中一个属性的反射信息
        /// </summary>
        /// <returns></returns>
        private string FindProName<T>()
        {
            string name = "";
            foreach (PropertyInfo pro in typeof(T).GetProperties())
            {
                if (!string.IsNullOrEmpty(pro.Name) && pro.PropertyType != typeof(Guid))
                {
                    if (pro.PropertyType == typeof(int) || pro.PropertyType == typeof(string))
                    {
                        name = pro.Name;
                        break;
                    }
                }
            }
            return name;
        }
        #endregion

      

       

        /// <summary>
        /// 根据指定的条件查询一个实体类
        /// </summary>
        /// <typeparam name="T">要查询的对象</typeparam>
        /// <param name="cons">查询条件集合</param>
        /// <returns></returns>
        public T GetOneObject<T>(Condition[] cons) where T : new()
        {
            using (ITransaction tx = _session.BeginTransaction())
            {
                try
                {
                    ICriteria criteria = _session.CreateCriteria(typeof(T));
                    criteria = this.GetICriteria(criteria, cons);
                    tx.Commit();
                    return criteria.UniqueResult<T>();
                }
                catch (HibernateException ex)
                {
                    tx.Rollback();
                    throw new Exception(ex.Message);
                }
            }

        }

        #region 增加 删除 更新
        /// <summary>
        /// 插入一条记录,同时返回新插入的identity值
        /// </summary>
        /// <param name="T">要插入的实体类对象</param>
        /// <returns>新id值</returns>
        public int Insert<T>(T obj) where T : new()
        {
            int newId = 0;
            using (ITransaction tx = _session.BeginTransaction())
            {
                try
                {
                    newId = (int)_session.Save(obj);
                    _session.Flush();
                    tx.Commit();
                }
                catch
                {
                    tx.Rollback();
                    newId = 0;
                }

            }
            return newId;
        }

        /// <summary>
        /// 插入，需要事务支持
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public int InsertByTrans<T>(T obj) where T : new()
        {
            int newId = 0;
            try
            {
                newId = (int)_session.Save(obj);
            }
            catch
            {

                newId = 0;
            }
            return newId;
        }

        

        /// <summary>
        /// 插入一条记录
        /// </summary>
        /// <param name="T">要插入的实体类对象</param>
        /// <returns>bool</returns>
        public bool InsertKeyIsGuid<T>(T obj) where T : new()
        {
            bool newId = true;
            using (ITransaction tx = _session.BeginTransaction())
            {
                try
                {
                    _session.Save(obj);
                    _session.Flush();
                    tx.Commit();
                }
                catch
                {
                    tx.Rollback();
                    newId = false;
                }

            }
            return newId;
        }

        /// <summary>
        /// 修改一条信息记录
        /// </summary>
        /// <param name="T">要修改的实体类对象</param>
        /// <param name="objId">要修改的实体类对象主键值</param>
        public bool Update<T>(T obj,object objId) where T : new()
        {
            bool isSuccess = true;
            using (ITransaction tx = _session.BeginTransaction())
            {
                try
                {
                    _session.Update(obj, objId);
                    _session.Flush();
                    tx.Commit();
                    isSuccess = true;
                }
                catch (HibernateException ex)
                {
                    tx.Rollback();
                    isSuccess = false;
                }
            }
            return isSuccess;
        }

        /// <summary>
        /// 修改一条信息记录
        /// </summary>
        /// <param name="T">要修改的实体类对象</param>
        public bool Update<T>(T obj) where T : new()
        {
            bool isSuccess = true;
            using (ITransaction tx = _session.BeginTransaction())
            {
                try
                {
                    _session.Update(obj);
                    _session.Flush();
                    tx.Commit();
                    isSuccess = true;
                }
                catch (HibernateException ex)
                {
                    tx.Rollback();
                    isSuccess = false;
                }
            }
            return isSuccess;
        }

        /// <summary>
        /// 删除一条信息记录
        /// </summary>
        /// <param name="T">要删除的实体类对象</param>
        public bool Delete<T>(T obj) where T : new()
        {
            bool isSuccess = true;
            using (ITransaction tx = _session.BeginTransaction())
            {
                try
                {
                    _session.Delete(obj);
                    _session.Flush();
                    tx.Commit();
                    isSuccess = true;
                }
                catch (HibernateException)
                {
                    tx.Rollback();
                    isSuccess = false;
                }
            }
            return isSuccess;
        }
        #endregion

        
    }
}
